﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.Management;
using TipokHostContract;
using TipokHostManager.Model;


namespace TipokHostManager.WMIManager
{
    /// <summary>
    /// Windows Service Manager
    /// 默认管理本机服务,管理远程不能用Instance，必须使用ServiceManager或者Instance.ManagementBaseInit进行设置
    /// </summary>
    public class ServiceManager : ManagementBase<ServiceManager>
    {
        public ServiceManager()
            : this(EnumWMICalassName.Win32_Service, ".", string.Empty, string.Empty)
        {
        }
        public ServiceManager(EnumWMICalassName classname, string host, string username, string password)
        {
            base.ManagementBaseInit(classname, host, username, password);
        }

        #region Methods
        public ReturnValue StartService(string serviceName)
        {
            return InvokeMethod(serviceName, "StartService");
        }

        public ReturnValue StopService(string serviceName)
        {
            return InvokeMethod(serviceName, "StopService");
        }

        public ReturnValue ResumeService(string serviceName)
        {
            return InvokeMethod(serviceName, "ResumeService");
        }

        public ReturnValue PauseService(string serviceName)
        {
            return InvokeMethod(serviceName, "PauseService");
        }

        //delete方法目前没有用，所以注释InvokeMethod(serviceName, "delete");

        /// <summary>
        /// 执行目录下的install.bat文件
        /// </summary>
        public ReturnValue InstallService(string workerPath)
        {
            return InvokeProcess(workerPath, "install");
        }

        /// <summary>
        /// 执行目录下的uninstall.bat文件
        /// </summary> 
        public ReturnValue UninstallService(string workerPath)
        {
            return InvokeProcess(workerPath, "uninstall");
        }

        public List<ServiceModel> GetAllServices()
        {
            var list = new List<ServiceModel>();
            foreach (ManagementObject mo in this.managementClass.GetInstances())
            {
                list.Add(ExtractServiceItem(mo));
            }
            return list;
        }

        public bool Exists(string serviceName)
        {
            ConnectionOptions options = new ConnectionOptions();
            ManagementScope scope = null;
            if (this.managementScope != null)
            {
                scope = this.managementScope;
                scope.Connect();
            }
            SelectQuery query = new SelectQuery(EnumWMICalassName.Win32_Service.ToString(), String.Format(CultureInfo.InvariantCulture, "Name='{0}'", serviceName));
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
            {
                ManagementObjectCollection moc = searcher.Get();
                return moc.Count > 0 ? true : false;
            }
        }

        public ServiceModel GetService(string serviceName)
        {
            using (ManagementObject mo = this.managementClass.CreateInstance())
            {
                //直接根据路径查找服务
                string path = string.Concat(this.managementPath, string.Format(".Name=\"{0}\"", serviceName));
                mo.Path = new ManagementPath(path);
                return ExtractServiceItem(mo);
            }
        }

        /// <summary>
        /// 返回所有状态的服务
        /// </summary>
        /// <param name="serviceNames">搜索的服务名</param>
        /// <param name="likeSearch">是否使用like搜索</param>
        /// <returns></returns>
        public List<ServiceModel> SearchServices(List<string> serviceNames, bool likeSearch)
        {
            return SearchServices(serviceNames, likeSearch, string.Empty);
        }

        public List<ServiceModel> SearchServices(List<string> serviceNames, bool likeSearch, string WqlWhere)
        {
            var list = new List<ServiceModel>();
            using (ManagementObject mo = this.managementClass.CreateInstance())
            {
                foreach (string serviceName in serviceNames)
                {
                    try
                    {
                        if (likeSearch)
                        {//搜索服务
                            foreach (string _path in FindServicesPathByKeyword(serviceName, WqlWhere))
                            {
                                mo.Path = new ManagementPath(_path);
                                list.Add(ExtractServiceItem(mo));
                            }
                        }
                        else
                        {//直接根据路径查找服务 
                            string path = string.Concat(this.managementPath, string.Format(".Name=\"{0}\"", serviceName));
                            if (!string.IsNullOrEmpty(WqlWhere))
                            {
                                if (!WqlWhere.ToUpper().Trim().StartsWith("AND"))
                                {
                                    path += " AND" + WqlWhere;
                                }
                                else
                                {
                                    path += WqlWhere;
                                }
                            }
                            mo.Path = new ManagementPath(path);
                            list.Add(ExtractServiceItem(mo));
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
                        {
                            //not find service nothing to do
                        }
                        else
                        {
                            throw ex;
                        }
                    }
                }
            }
            return list;
        }

        private List<string> FindServicesPathByKeyword(string serviceNameKeyword, string WqlWhere)
        {
            ConnectionOptions options = new ConnectionOptions();
            ManagementScope scope = null;
            if (this.managementScope != null)
            {
                scope = this.managementScope;
                scope.Connect();
            }
            string path = String.Format(CultureInfo.InvariantCulture, "Name like \"%{0}%\"", serviceNameKeyword);
            if (!string.IsNullOrEmpty(WqlWhere))
            {
                if (!WqlWhere.ToUpper().Trim().StartsWith("AND"))
                {
                    path += " AND" + WqlWhere;
                }
                else
                {
                    path += WqlWhere;
                }
            }
            SelectQuery query = new SelectQuery(EnumWMICalassName.Win32_Service.ToString(), path);
            List<string> _list = new List<string>();
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
            {
                ManagementObjectCollection moc = searcher.Get();
                foreach (var item in moc)
                {
                    //RELPATH
                    _list.Add(item.SystemProperties["__PATH"].Value.ToString());
                }
            }
            return _list;
        }
        #endregion 
    }
}
